package org.durandj.ystream.server.playlist;

import java.security.InvalidParameterException;
import java.util.LinkedList;

/**
 * Represents the current playlist and everything in it. When the playlist
 * is changed it notifies anything that is listening for changes as to what happened.
 * 
 * @author durandj
 * @version 1.0
 *
 */
public class Playlist
{
	/**
	 * Elements in the playlist. This list contains the file names.
	 */
	private LinkedList<String> elements;
	
	/**
	 * The list of listeners for this playlist.
	 */
	private LinkedList<PlaylistListener> listeners;
	
	/**
	 * Max number of items allowed in the playlist.
	 */
	private int maxElements;
	
	/**
	 * Constructs an empty playlist.
	 */
	public Playlist()
	{
		elements = new LinkedList<String>();
		listeners = new LinkedList<PlaylistListener>();
		maxElements = -1;
	}
	
	/**
	 * Clears the entire playlist.
	 */
	public void clear()
	{
		elements.clear();
		
		// Let the listeners know what happened.
		for(PlaylistListener l : listeners)
			l.listCleared();
	}
	
	/**
	 * Adds a new file to the playlist.
	 * 
	 * @param element - the new item
	 */
	public void add(String element)
	{
		if(element == null)
			throw new NullPointerException("Must give a valid item.");
		
		if(elements.size() == maxElements)
			return;
		
		elements.add(element);

		// Let the listeners know what happened.
		for(PlaylistListener l : listeners)
			l.itemAdded(element);
	}
	
	/**
	 * Removes a file from the playlist.
	 * 
	 * @param element - the element to remove
	 */
	public void remove(String element)
	{
		if(element == null)
			throw new NullPointerException("Must give a valid item.");
		
		elements.remove(element);
		
		// Let the listeners know what happened.
		for(PlaylistListener l : listeners)
			l.itemRemoved(element);
	}
	
	/**
	 * Removes a file from the playlist.
	 * 
	 * @param index - the index of the element
	 */
	public void remove(int index)
	{
		if(index < 0 || index >= size())
			throw new InvalidParameterException("Must give a valid index.");
		
		String item = elements.remove(index);
		
		// Let the listeners know what happened.
		for(PlaylistListener l : listeners)
			l.itemRemoved(item);
	}
	
	/**
	 * Gets the number of items in the playlist.
	 * @return
	 */
	public int size()
	{
		return elements.size();
	}
	
	/**
	 * Checks if the playlist is empty.
	 * 
	 * @return is it empty?
	 */
	public boolean isEmpty()
	{
		return elements.isEmpty();
	}
	
	public int getMaxElements()
	{
		return maxElements;
	}
	
	/**
	 * Sets the maximum number of elements allowed in the playlist. This can
	 * be negative which means that the playlist can hold any number of items.
	 * 
	 * @param maxElements - the max number of elements
	 */
	public void setMaxElements(int maxElements)
	{
		this.maxElements = maxElements;
		
		// We may need to drop some things from the playlist to account for the new max.
		if(maxElements < elements.size())
		{
			for(int i = elements.size() - 1; i >= maxElements; i++)
				elements.remove(i);
		}
	}
	
	/**
	 * Gets an item from the playlist.
	 * 
	 * @param index - the index
	 * @return the item
	 */
	public String get(int index)
	{
		if(index < 0 || index >= size())
			throw new InvalidParameterException("Must give a valid index.");
		
		return elements.get(index);
	}
	
	/**
	 * Gets the entire array of values from the playlist.
	 * 
	 * @return all the elements in the playlist
	 */
	public String[] getAll()
	{
		String ret[] = new String[size()];
		elements.toArray(ret);
		
		return ret;
	}
	
	/**
	 * Moves an item up in the playlist.
	 * 
	 * @param index - the current index of the item
	 */
	public void moveUp(int index)
	{
		if(index < 0 || index >= size())
			throw new InvalidParameterException("Must give a valid index.");
		
		String temp = get(index);
		elements.set(index, elements.get(index - 1));
		elements.set(index - 1, temp);
		
		// Let the listeners know what happened.
		for(PlaylistListener l : listeners)
			l.itemMoved(temp, index - 1);
	}
	
	/**
	 * Moves an item down in the playlist.
	 * 
	 * @param index - the current index of the item
	 */
	public void moveDown(int index)
	{
		if(index < 0 || index >= size())
			throw new InvalidParameterException("Must give a valid index.");
		
		String temp = get(index);
		elements.set(index, elements.get(index + 1));
		elements.set(index + 1, temp);
		
		// Let the listeners know what happened.
		for(PlaylistListener l : listeners)
			l.itemMoved(temp, index + 1);
	}
	
	/**
	 * Add a listener to the playlist to listen for changes.
	 * 
	 * @param listener - the new listener
	 */
	public void addListener(PlaylistListener listener)
	{
		if(listener == null)
			throw new NullPointerException("Must give a valid listener.");
		
		listeners.add(listener);
	}
	
	/**
	 * Removes a listener from the list of playlist listeners.
	 * 
	 * @param listener - the listener to remove
	 */
	public void removeListener(PlaylistListener listener)
	{
		if(listener == null)
			throw new NullPointerException("Must give a valid listener.");
		
		listeners.remove(listener);
	}
}
